using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Threading;
using System.Globalization;
using Microsoft.MediaCenter.UI;
using Microsoft.MediaCenter.Hosting;
using Level65.ClipShow;
using Level65.WMVHelper;

namespace ClipShow 
{
    public enum FocusAreas
    {
        PreviewTiles, ToplineSelection, 
        MenuBar, SelectionTiles, TagTiles, 
        TimelineTiles, SnagTiles, Debug, PlaylistSelectionTiles, 
        MediaPlayTiles, LinkedTiles, VideoTile, ButtonBar
    }
    internal enum MetadataDescriptor
    {
        ItemTitle, ItemDescription
    }
    public enum TileViewType {Topics, Timeline, PlayLists, Snags, SingleMediaItem}
    public sealed class PciTimelineComparer : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            PreviewChannelItem firstInstance = x as PreviewChannelItem;
            PreviewChannelItem secondInstance = y as PreviewChannelItem;

            int firstDay = 2;
            int secondDay = 2;

            if (firstInstance.TimelineMonth.Equals(0))
            {
                firstInstance.TimelineMonth = 1;
                firstDay = 1;
            }

            if (secondInstance.TimelineMonth.Equals(0))
            {
                secondInstance.TimelineMonth = 1;
                secondDay = 1;
            }

            DateTime firstItem = new DateTime(firstInstance.TimelineYear, firstInstance.TimelineMonth, firstDay);
            DateTime secondItem = new DateTime(secondInstance.TimelineYear, secondInstance.TimelineMonth,secondDay);

            return( firstItem.CompareTo(secondItem));
        }
    }
    public sealed class PciComparer : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            PreviewChannelItem firstInstance = x as PreviewChannelItem;
            PreviewChannelItem secondInstance = y as PreviewChannelItem;
            return firstInstance.Name.CompareTo(secondInstance.Name);
        }
    }
    public sealed class MediaComparer : System.Collections.IComparer
    {
        public int Compare(object x, object y)
        {
            MediaMetaData firstInstance = x as MediaMetaData;
            MediaMetaData secondInstance = y as MediaMetaData;
            return firstInstance.Title.CompareTo(secondInstance.Title);
        }
    }
    public class PreviewChannelItem : ClipItem
    {
        private Image _thumbnail;
        private int _timelineYear;
        private int _timelineMonth;
        
        public PreviewChannelItem()
        {
        }

        public Image Thumbnail
        {
            get { return (_thumbnail);}
            set { _thumbnail = value;}
        }
        public int TimelineYear
        {
            get { return (_timelineYear); }
            set { _timelineYear = value; }
        }
        public int TimelineMonth
        {
            get { return (_timelineMonth); }
            set { _timelineMonth = value; }
        }

    }
    public class CommandBarItem
    {
        private string _commandName = "";
        private string _commandDescription = "";

        public CommandBarItem(string commandName, string commandDescription)
        {
            _commandName = commandName;
            _commandDescription = commandDescription;
        }

        public string CommandName
        {
            get {return (_commandName);}
            set {_commandName = value;}
        }

        public string CommandDescription
        {
            get {return (_commandDescription);}
            set {_commandDescription = value;}
        }

    }
    public class FilterBarItem
    {
        private TileViewType _filterType = TileViewType.SingleMediaItem;
        private string _filterName;
        private string _filterDescription;

        public FilterBarItem(string filterName, string filterDescription, TileViewType filterType)
        {
            _filterName = filterName;
            _filterDescription = filterDescription;
            _filterType = filterType;
        }
        public TileViewType FilterType
        {
            get { return (_filterType); }
            set { _filterType = value; }
        }
        public string FilterName
        {
            get { return (_filterName); }
            set { _filterName = value; }
        }
        public string FilterDescription
        {
            get { return (_filterDescription); }
            set { _filterDescription = value; }
        }
    }
    public class CoreUICodeBehind : ModelItem
    {
        // Constants
        private const string APP_NAME = "clipShow";

        // ModelItem intrinsics
        private Command _updateStatusBar;
        private Command _commandBarClick;
        private Command _clippingOveride;
        private Command _showTimelineFilter;
        private Command _showSnagFilter;
        private Command _showVisualTagFilter;
        private Command _showPlaylistFilter;
        private Command _showTagFilter;
        private Command _showSingleFilter;
        private Choice _commandBarItems;
        private Choice _browseTiles;
        private Choice _myMediaLibraries;
        private Choice _myMediaContentItems;
        private Choice _myMediaFilters;
        private Command _hideSelections;

        // Private variables
        private int _currentFocusedVideoIndex;
        private FocusAreas _currentFocusArea;
        private int _currentTopicIndex = -1;
        private int _currentMenuIndex ;
        private int _currentTileIndex;
        private int _lastCommandIndex;
        internal int _currentShowingVideoIndex;
        private string _debugInfo = "";
        private bool _remoteActivity;
        private bool _isInHidden;
        private bool _playlistCreation;
        private string _buttonBarDescription;
        private Dictionary<TileViewType, Command> _cachedTiles = new Dictionary<TileViewType,Command>();
        private Dictionary<int, ArrayListDataSet> _cachedMediaItems = new Dictionary<int, ArrayListDataSet>();
        private TileViewType _currentView = TileViewType.SingleMediaItem;
        private PreviewChannelItemList _myMediaVItems = new PreviewChannelItemList();
        private PreviewChannelItemList _myTimelineVItems = new PreviewChannelItemList();
        private string _lastVideoSource;
        private Settings _settings = new Settings();

        public CoreUICodeBehind()
        {
            _updateStatusBar = new Command();
            _commandBarClick = new Command();
            _myMediaContentItems = new Choice();
            _commandBarItems = new Choice();
            _currentFocusArea = FocusAreas.ToplineSelection;
            _clippingOveride = new Command();
            _hideSelections = new Command();
            _showTimelineFilter = new Command();
            _showSnagFilter = new Command();
            _showVisualTagFilter = new Command();
            _showPlaylistFilter = new Command();
            _showTagFilter = new Command();
            _showSingleFilter = new Command();
            _myMediaFilters = new Choice();
            Storage st = new Storage();
            _settings = st.GetSettings();
        }

        #region Core properties
        public Settings AppSettings
        {
            get { return (_settings);}
            set { _settings = value;}
        }
        public FocusAreas CurrentFocusArea
        {
            get { return (_currentFocusArea); }
            set { _currentFocusArea = value;  }
        }

        public TileViewType CurrentView
        {
            get { return(_currentView); }
            set { _currentView = value; }
        }
         public Command HideSelectionControls
        {
            get { return (_hideSelections); }
        }
        public Command ShowTimelineFilterItems
        {
            get {return(_showTimelineFilter);}
        }
        public Command ShowSnagFilterItems
        {
            get { return (_showSnagFilter); }
        }
        public Command ShowVisualTagFilterItems
        {
            get { return (_showVisualTagFilter); }
        }
        public Command ShowPlaylistFilterItems
        {
            get { return (_showPlaylistFilter); }
        }
        public Command ShowTagFilterItems
        {
            get { return (_showTagFilter); }
        }
        public Command ShowSingleFilterItems
        {
            get { return (_showSingleFilter); }
        }
        public int CurrentTileIndex
        {
            get { return (_currentTileIndex);}
            set { _currentTileIndex = value;}
        }
        public int LastCommandIndex
        {
            get { return (_lastCommandIndex);}
            set { _lastCommandIndex = value;}
        }
        public int CurrentToplineIndex
        {
            get { return (_currentTopicIndex);}
            set { _currentTopicIndex = value;}
        }
        public int CurrentFocusVideoIndex
        {
            get { return (_currentFocusedVideoIndex);}
            set { _currentFocusedVideoIndex = value; }
        }
        public Command UpdateStatusBar
        {
            get { return (_updateStatusBar); }
        }
        public Command ClipNotification
        {
            get { return (_clippingOveride); }
        }
        public Choice BrowseTiles
        {
            get { return (_browseTiles);}
            set { _browseTiles = value; }
        }
        public Choice CommandBarItems
        {
            get { return (_commandBarItems); }
        }

        private MediaList _wmvMetaDataV3 = new MediaList();
        public MediaList VideoMetaDataList
        {
            get { return (_wmvMetaDataV3); }
            set { _wmvMetaDataV3 = value; }
        }
        public static string ApplicationName
        {
            get { return (APP_NAME); }
        }

        public bool RemoteActivity
        {
            get { return (_remoteActivity);}
            set { _remoteActivity = value;}
        }
        public bool FlagHidden
        {
            set { _isInHidden = value;}
            get { return (_isInHidden);}
        }
        internal static string GetDescriptionText(MediaMetaData source, MetadataDescriptor target)
        {
            string resultText = "Not available";
            try
            {
                if (target.Equals(MetadataDescriptor.ItemDescription))
                {
                    if (source.Description.Length > 0)
                    {
                        resultText = source.Description;
                    }
                    else
                    {
                        if (source.Title.Length > 0)
                        {
                            resultText = source.Title;
                        }
                        else
                        {
                            resultText = Path.GetFileNameWithoutExtension(source.Url);
                        }
                    }
                }
                if (target.Equals(MetadataDescriptor.ItemTitle))
                {
                    if (source.Title.Length > 0)
                    {
                        resultText = source.Title;
                    }
                    else
                    {
                        resultText = Path.GetFileNameWithoutExtension(source.Url);
                    }
                }
            }
            catch
            {

            }
            return (resultText);
        }
        public static MediaBrowseCodeBehind ReturnNewBrowserPage
        {
            get { return (new MediaBrowseCodeBehind());}
        }
        public bool CreatePlaylistMode
        {
            get { return (_playlistCreation); }
            set { _playlistCreation = value;  }
        }
        /// <summary>
        /// Property that handles what to display in the bottom status bar
        /// </summary>
        public string CurrentBrowseStatus
        {
            get
            {
                string prefix = "watch";
                if (_playlistCreation)
                {
                    prefix = "add to playlist";
                }
                this.RemoteActivity = true;
                this.FlagHidden = false;

                if (_currentFocusArea.Equals(FocusAreas.ButtonBar))
                {
                    return (_buttonBarDescription);
                }

                if (_currentFocusArea.Equals(FocusAreas.VideoTile))
                {
                    try
                    {
                        MediaListItem item = (MediaListItem)this.VideoMetaDataList[_currentShowingVideoIndex];
                        if (AppSettings.UseVMCFullScreen)
                        {
                            return (String.Format("watch '{0}' in full screen (click the Back button to return)", item.SourceItem.Title));
                        }
                        else
                        {
                            return (String.Format("watch '{0}' in full screen (click OK or hit Enter to return)", item.SourceItem.Title));
                        }
                    }
                    catch
                    {
                        // Bug
                        return ("ready");
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.LinkedTiles))
                {
                    MediaListItem med = (MediaListItem)this.VideoMetaDataList[_currentTileIndex];
                    if (!_playlistCreation)
                    {
                        return (String.Format("{0} '{1}' and create a playlist of linked media", prefix, med.SourceItem.Title));
                    }
                    else
                    {
                        return (String.Format("{0} '{1}'", prefix, med.SourceItem.Title));
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.PlaylistSelectionTiles))
                {
                    MediaMetaData med = (MediaMetaData)_browseTiles.Options[_currentFocusedVideoIndex];
                    if (_playlistCreation)
                    {
                        return (String.Format("remove '{0}' from playlist", GetDescriptionText(med, MetadataDescriptor.ItemTitle)));
                    }
                    else
                    {
                        return (GetDescriptionText(med, MetadataDescriptor.ItemTitle));
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.SnagTiles))
                {
                    PreviewChannelVItem item = (PreviewChannelVItem)_browseTiles2[_currentTileIndex];
                    if (item.SourceItem.Keywords.Equals("ALL"))
                    {
                        return (String.Format("{0} all snagged clips", prefix));
                    }
                    else
                    {
                        return (String.Format("{0} snagged clips from '{1}'", prefix, item.SourceItem.Name));
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.TimelineTiles))
                {
                    PreviewChannelVItem item = (PreviewChannelVItem)_browseTiles2[_currentTileIndex];
                    if (( item.SourceItem.Name.StartsWith("2") ) || ((item.SourceItem.Name.StartsWith("1"))))
                    {
                        return (String.Format("{0} clips from {1}", prefix, item.SourceItem.LongName));
                    }
                    else
                    {
                        //return (String.Format("{0} clips from {1} of {2}", prefix, MonthConvert(item.SourceItem.TimelineMonth), item.SourceItem.TimelineYear));                        
                        return (String.Format("{0} clips from {1}", prefix, item.SourceItem.LongName));
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.TagTiles))
                {
                    PreviewChannelVItem item = (PreviewChannelVItem)_browseTiles2[_currentTileIndex];
                    return (String.Format("{0} clips tagged by '{1}' ({2} items)", prefix, item.SourceItem.Name, item.SourceItem.Count));
                }
                if (_currentFocusArea.Equals(FocusAreas.MediaPlayTiles))
                {
                    MediaListItem item = (MediaListItem)_browseTiles3[_currentFocusedVideoIndex];
                    if (this.CreatePlaylistMode)
                    {
                        return (String.Format("remove '{0}' from playlist", GetDescriptionText(item.SourceItem, MetadataDescriptor.ItemTitle)));
                    }
                    else
                    {
                        return (String.Format("play '{0}'", GetDescriptionText(item.SourceItem, MetadataDescriptor.ItemTitle)));
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.SelectionTiles))
                {
                    PreviewChannelVItem item = (PreviewChannelVItem)_browseTiles2[_currentTileIndex];
                    return (String.Format("{0} '{1}' playlist ({2} items)", prefix, item.SourceItem.Name, item.SourceItem.Count));
                }
                if (_currentFocusArea.Equals(FocusAreas.PreviewTiles))
                {
                    if (_browseTiles.Options[_currentTileIndex].GetType().ToString().Equals("Level65.ClipShow.MediaMetaData"))
                    {
                        MediaMetaData item = (MediaMetaData)_browseTiles.Options[_currentTileIndex];
                        return (GetDescriptionText(item, MetadataDescriptor.ItemTitle));
                    }
                    if (_browseTiles2[_currentTileIndex].GetType().ToString().Equals("ClipShow.PreviewChannelVItem"))
                    {
                        if (_currentTileIndex >= 0)
                        {
                            PreviewChannelVItem ci = (PreviewChannelVItem)_browseTiles2[_currentTileIndex];
                            return (String.Format("{0} '{1}' playlist", prefix, ci.SourceItem.Name));
                        }
                    }

                }

                if (_currentFocusArea.Equals(FocusAreas.ToplineSelection))
                {
                    if (_browseTiles.Options[_currentTopicIndex].GetType().ToString().Equals("ClipShow.FilterBarItem"))
                    {
                        FilterBarItem fbi = (FilterBarItem)_browseTiles.Options[_currentTopicIndex];
                        return (fbi.FilterDescription);
                    }
                    if (_browseTiles.Options[_currentTopicIndex].GetType().ToString().Equals("ClipShow.PreviewChannelItem"))
                    {
                        ClipItem ci = (ClipItem)_browseTiles.Options[_currentTopicIndex];
                        return (String.Format("watch '{0}' clips ({1} items)", ci.Name,
                            ci.Count));
                    }
                    if (_browseTiles.Options[_currentTopicIndex].GetType().ToString().Equals("Level65.ClipShow.ClipShowContent"))
                    {
                        ClipShowContent cm = (ClipShowContent)_browseTiles.Options[_currentTopicIndex];
                        if (cm.ContentSourceName.Equals("my snags"))
                        {
                            return ("browse your snagged clips");
                        }
                        else
                        if (cm.ContentSourceName.Equals("my playlists"))
                        {
                            return ("browse your playlists");
                        }
                        else
                        {
                            return (String.Format("browse '{0}' playlist ({1} categories)",
                                cm.ContentSourceName, cm.KeywordItems.Count));
                        }
                        
                    }
                }
                if (_currentFocusArea.Equals(FocusAreas.Debug))
                {
                    return (_debugInfo);
                }
                if (_currentFocusArea.Equals(FocusAreas.MenuBar))
                {
                    CommandBarItem cbi = (CommandBarItem)_commandBarItems.Options[_currentMenuIndex];
                    if (cbi.CommandName.Equals("Duration"))
                    {
                        return(String.Format("change current playback duration to {0}",
                            this.AppSettings.NextClipLength));
                    }
                    else if ( (cbi.CommandName.Equals("Linked") ) || (cbi.CommandName.Equals("Snag")) 
                        || (cbi.CommandName.Equals("Full")))
                    {
                        MediaListItem item = (MediaListItem)this.VideoMetaDataList[this.CurrentFocusVideoIndex];
                        return (String.Format(cbi.CommandDescription, item.SourceItem.Title));
                    }
                    else
                    {
                        return (cbi.CommandDescription);
                    }
                }
                else
                {
                    return ("ready");
                }
            }
        }

        public Choice MediaFilters
        {
            get { return (_myMediaFilters); }
            set { _myMediaFilters = value; }
        }
        public Choice MediaLibraries
        {
            get { return (_myMediaLibraries); }
        }
        public Choice MediaLibraryItems
        {
            get { return (_myMediaContentItems); }
        }
        public PreviewChannelItemList MediaLibraryList
        {
            get { return (_myMediaVItems); }
        }

        public PreviewChannelItemList TimelineMediaLibraryList
        {
            get { return(_myTimelineVItems); }
        }
        public PreviewChannelItemList SnagMediaLibraryList
        {
            get { return (_mySnagMediaContentVItems); }
        }
        private PreviewChannelItemList _mySnagMediaContentVItems = new PreviewChannelItemList();
        private PreviewChannelItemList _myPlaylistMediaContentVItems = new PreviewChannelItemList();
        public PreviewChannelItemList PlaylistMediaLibraryList
        {
            get { return (_myPlaylistMediaContentVItems); }
        }
        private PreviewChannelItemList _myTagMediaContentVItems = new PreviewChannelItemList();
        public PreviewChannelItemList TagMediaLibraryList
        {
            get { return (_myTagMediaContentVItems); }
        }
        public Command CommandBarClicked
        {
            get { return (_commandBarClick);}
        }
        public CoreUICodeBehind CoreUI
        {
            get { return (this);}
        }
        public int CurrentMenuIndex
        {
            get { return (_currentMenuIndex);}
        }
        public PageSession MySession 
        {
            get { return (Microsoft.MediaCenter.Hosting.HistoryOrientedPageSession.Current);}
        }
        #endregion

        #region Core methods
        internal static bool CheckForKeyword(MediaMetaData source, string keyword)
        {
            bool result = false;
            result = ((source.Description.Contains(keyword)) ||
                (source.Title.Contains(keyword)) ||
                (source.Url.Contains(keyword)));
            return (result);
        }

        public MediaPlayCodeBehind ResultPageAll
        {
            get
            {
                ClipCollection allMedia = new ClipCollection();
                allMedia.ClipLength = MediaClipLengths.Medium;
                allMedia.Name = "All Video";
                MediaPlayCodeBehind cb = new MediaPlayCodeBehind();
                int Ctr = 0;

                foreach (ClipShowContent playList in this.MediaLibraries.Options)
                {
                    foreach (MediaMetaData item in playList.MediaItems)
                    {
                        if (!item.Title.Equals("N/A"))
                        {
                            if (Ctr == 0)
                            {
                                MediaListItem mli = new MediaListItem(item);
                                mli.SourceItem.Thumbnail = new Image(BuildImagePath(mli.SourceItem.ThumbnailUrl));
                                cb.VideoMetaDataList.Add(mli);
                                Ctr = 1;
                            }
                            else
                            {
                                cb.TileItems.Add(item);
                            }
                        }
                    }
                }

                Random r = new Random(unchecked((int)DateTime.Now.Ticks));
                RandomizeArrayListDataSet(cb.TileItems, r);

                cb.CurrentChannel = allMedia;
                cb.PopulateTiles();
                cb.PlayClip();

                return (cb);
            }
        }

        public static MediaList AddItems(ArrayListDataSet source)
        {
            MediaList results = new MediaList();
            foreach (MediaMetaData med in source)
            {
                MediaListItem mli = new MediaListItem();
                mli.SourceItem = med;
                results.Add(mli);
            }
            return (results);
        }
        public void ShowDialog(string dialogCaption, string dialogMessage, bool isModal)
        {
            try
            {
                AddInHost.Current.MediaCenterEnvironment.Dialog(dialogMessage,
                    dialogCaption, Microsoft.MediaCenter.DialogButtons.Ok, 15000, isModal);
            }
            catch
            {
                // Do nothing; most likely running in MCMLPad
            }
        }

        public void ShuffleClips()
        {
            Random r = new Random(unchecked((int)DateTime.Now.Ticks));
            RandomizeMediaList(this.VideoMetaDataList, r);
        }

        public void BuildMediaTopics(int libraryIndex)
        {
            ClipShowContent cm = (ClipShowContent)this.MediaLibraries.Options[libraryIndex];
            if (cm.ContentSourceName.Equals("my snags"))
            {
                ArrayListDataSet tempResults = new ArrayListDataSet();

                long snagCtr = 0;
                foreach (MediaMetaData ci in cm.MediaItems)
                {
                    PreviewChannelItem pci = new PreviewChannelItem();
                    pci.Count = ci.SnagList.Count;
                    snagCtr += ci.SnagList.Count;
                    pci.Keywords = ci.Title;
                    pci.Thumbnail = new Image(BuildImagePath(ci.ThumbnailUrl));
                    pci.Name = ci.Title;
                    pci.MediaItems.Add(ci);
                    tempResults.Add(pci);
                }

                // Now parent snag first
                PreviewChannelItem parent = new PreviewChannelItem();
                parent.Name = "All snags";
                MediaMetaData temp = (MediaMetaData)cm.MediaItems[0];
                parent.ThumbnailUrl = temp.ThumbnailUrl;
                parent.Count = snagCtr;
                parent.Thumbnail = new Image(BuildImagePath(temp.ThumbnailUrl));
                parent.Keywords = "ALL";
                parent.MediaItems.Add(temp);
                tempResults.Add(parent);

                IComparer myComparer = new PciComparer();
                tempResults.Sort(myComparer);
                _myMediaContentItems.Options = tempResults;
            }
            else
            if (!cm.ContentSourceName.Equals("my playlists"))
            {
                ArrayListDataSet tempResults = new ArrayListDataSet();
                foreach (ClipItem ci in cm.KeywordItems)
                {
                    PreviewChannelItem pci = new PreviewChannelItem();
                    pci.Count = ci.Count;
                    pci.Keywords = ci.Keywords;
                    pci.Thumbnail = new Image(BuildImagePath(ci.ThumbnailUrl));
                    pci.Name = ci.Name;
                    tempResults.Add(pci);
                }
                IComparer myComparer = new PciComparer();
                tempResults.Sort(myComparer);
                _myMediaContentItems.Options = tempResults;
            }
            else
            {
                ArrayListDataSet tempResults = new ArrayListDataSet();
                Storage st = new Storage();
                foreach (ClipCollection mc in st.GetMyCollections())
                {
                    PreviewChannelItem pci = new PreviewChannelItem();

                    ClipItem ci = (ClipItem)mc.Items[0];
                    pci.Count = ci.Count;
                    pci.Keywords = ci.Keywords;
                    pci.MediaChannelUri = mc.MediaSourceFilePath;
                    pci.Thumbnail = new Image(GetUniqueThumbnail(mc));
                    pci.Name = mc.Name;
                    tempResults.Add(pci);
                }
                _myMediaContentItems.Options = tempResults;
            }

        }

        private Dictionary<string, string> _usedThumbs = new Dictionary<string,string>();
        
        /// <summary>
        /// Return a unique thumbnail for the topic if one exists
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private string GetUniqueThumbnail(ClipCollection source)
        {
            string resultThumbnailPath = "";
            if (!AppSettings.UseEffects)
            {
                resultThumbnailPath = "resx://ClipShow/ClipShow.Resources/clipShow_glyph";
            }
            else
            {
                if (_usedThumbs.Count > 0)
                {
                    bool foundUnique = false;
                    foreach (ClipItem ci in source.Items)
                    {

                        if (!_usedThumbs.ContainsKey(ci.ThumbnailUrl))
                        {
                            resultThumbnailPath = BuildImagePath(ci.ThumbnailUrl);
                            _usedThumbs.Add(ci.ThumbnailUrl, resultThumbnailPath);
                            foundUnique = true;
                            break;
                        }
                    }
                    // If we are unable to find a new thumbnail, default to first one
                    if (!foundUnique)
                    {
                        ClipItem ci = (ClipItem)source.Items[0];
                        resultThumbnailPath = BuildImagePath(ci.ThumbnailUrl);
                    }
                }
                else
                {
                    ClipItem ci = (ClipItem)source.Items[0];
                    resultThumbnailPath = BuildImagePath(ci.ThumbnailUrl);
                    _usedThumbs.Add(ci.ThumbnailUrl, resultThumbnailPath);
                }
            }
            return (resultThumbnailPath);
        }

        public void BuildMediaTags()
        {
            ArrayListDataSet tempResults = new ArrayListDataSet();
            // Now iterate and build out tag list for all media (except custom clip
            foreach (ClipShowContent cm in this.MediaLibraries.Options)
            {
                if (!cm.ContentSourceName.Equals("my playlists"))
                {
                    foreach (ClipItem ci in cm.KeywordItems)
                    {
                        if (!ci.Keywords.Equals("ALL"))
                        {
                            bool result = false;
                            foreach (PreviewChannelItem pciItem in tempResults)
                            {
                                if (pciItem.Keywords.Equals(ci.Keywords))
                                {
                                    pciItem.Count += ci.Count;
                                    result = true;
                                    break;
                                }
                            }

                            if (!result)
                            {
                                PreviewChannelItem pci = new PreviewChannelItem();
                                pci.Count = ci.Count;
                                pci.Keywords = ci.Keywords;
                                pci.Thumbnail = new Image(BuildImagePath(ci.ThumbnailUrl));
                                pci.Name = ci.Name;
                                tempResults.Add(pci);
                            }
                        }
                    }
                }
            }

            // Check we have tags
            if (tempResults.Count > 0)
            {
                // Sort final results
                IComparer myComparer = new PciComparer();
                tempResults.Sort(myComparer);
                this.TagMediaLibraryList.Source = tempResults;
                _showTagFilter.Invoke();
                _cachedTiles.Add(TileViewType.Topics, _showTagFilter);
            }
        }



        public void BuildMediaByFilter(FilterBarItem source)
        {
            // Check cache first
            if (source.FilterType.Equals(this.CurrentView))
            {
                if (!this.CurrentView.Equals(TileViewType.SingleMediaItem))
                {
                    if (_cachedTiles.Count > 0)
                    {
                        return;
                    }
                }
            }

            if (_cachedTiles.ContainsKey(source.FilterType))
            {
                this.CurrentView = source.FilterType;
                _cachedTiles[source.FilterType].Invoke();
                _lastVideoSource = "";
            }
            else
            {
                if (source.FilterType.Equals(TileViewType.SingleMediaItem))
                {
                    if (!source.FilterName.Equals(_lastVideoSource))
                    {
                        Storage st = new Storage();
                        this.CurrentView = TileViewType.SingleMediaItem;
                        foreach (ClipShowContent cms in st.GetMediaLibraries())
                        {
                            if (source.FilterName.Equals(cms.ContentSourceName))
                            {
                                IComparer myComparer = new MediaComparer();
                                cms.MediaItems.Sort(myComparer);
                                this.VideoMetaDataList.Clear();

                                foreach (MediaMetaData item in cms.MediaItems)
                                {
                                    item.Parent = source.FilterName;
                                    Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepThumbnail), 
                                        new DeferredHandler(PostThumbnail), item);
                                }
                                break;
                            }
                        }

                        if (st.GetMediaLibraryCount() > 0)
                        {
                            _lastVideoSource = source.FilterName;
                        }
                        _showSingleFilter.Invoke();
                    }
                }
                #region Build view by snags
                if (source.FilterType.Equals(TileViewType.Snags))
                {
                    _lastVideoSource = "";
                    Storage st = new Storage();
                    this.CurrentView = TileViewType.Snags;
                    ArrayListDataSet tempResults = new ArrayListDataSet();
                    ClipShowContent cm = st.GetSnagCollection();
                    long snagCtr = 0;
                    foreach (MediaMetaData ci in cm.MediaItems)
                    {
                        PreviewChannelItem pci = new PreviewChannelItem();
                        pci.Count = ci.SnagList.Count;
                        snagCtr += ci.SnagList.Count;
                        pci.Keywords = ci.Title;
                        if (AppSettings.UseEffects)
                        {
                            pci.Thumbnail = new Image(BuildImagePath(ci.ThumbnailUrl));
                        }
                        else
                        {
                            pci.Thumbnail = new Image("resx://ClipShow/ClipShow.Resources/clipShow_glyph");
                        }
                        pci.Name = ci.Title;
                        pci.MediaItems.Add(ci);
                        tempResults.Add(pci);
                    }

                    // Now parent snag first
                    PreviewChannelItem parent = new PreviewChannelItem();
                    parent.Name = "All snags";
                    MediaMetaData temp = (MediaMetaData)cm.MediaItems[0];
                    parent.ThumbnailUrl = temp.ThumbnailUrl;
                    parent.Count = snagCtr;
                    if (AppSettings.UseEffects)
                    {
                        parent.Thumbnail = new Image(BuildImagePath(temp.ThumbnailUrl));
                    }
                    else
                    {
                        parent.Thumbnail = new Image("resx://ClipShow/ClipShow.Resources/clipShow_glyph");
                    }
                    parent.Keywords = "ALL";
                    parent.MediaItems.Add(temp);
                    tempResults.Add(parent);

                    IComparer myComparer = new PciComparer();
                    tempResults.Sort(myComparer);
                    _mySnagMediaContentVItems.Source = tempResults;
                    _cachedTiles.Add(source.FilterType, _showSnagFilter);
                    _showSnagFilter.Invoke();
                }
                #endregion

                #region Build view by playlist filter
                if (source.FilterType.Equals(TileViewType.PlayLists))
                {
                    _lastVideoSource = "";
                    this.CurrentView = TileViewType.PlayLists;
                    ArrayListDataSet tempResults = new ArrayListDataSet();
                    Storage st = new Storage();
                    foreach (ClipCollection mc in st.GetMyCollections())
                    {
                        PreviewChannelItem pci = new PreviewChannelItem();

                        ClipItem ci = (ClipItem)mc.Items[0];
                        pci.Count = ci.Count;
                        pci.Keywords = ci.Keywords;
                        pci.MediaChannelUri = mc.MediaSourceFilePath;
                        pci.Thumbnail = new Image(GetUniqueThumbnail(mc));
                        pci.ThumbnailUrl = GetUniqueThumbnail(mc);
                        pci.Name = mc.Name;
                        tempResults.Add(pci);
                    }

                    IComparer myComparer = new PciComparer();
                    tempResults.Sort(myComparer);
                    _myPlaylistMediaContentVItems.Source = tempResults;
                    _cachedTiles.Add(source.FilterType, _showPlaylistFilter);
                    _showPlaylistFilter.Invoke();
                }
                #endregion

                #region Build view by the timeline filter
                if (source.FilterType.Equals(TileViewType.Timeline))
                {
                    _lastVideoSource = "";
                    this.CurrentView = TileViewType.Timeline;
                    ArrayListDataSet tempResults = new ArrayListDataSet();
                    Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepTimeline), 
                        new DeferredHandler(PostTimeline), tempResults);
                    _showTimelineFilter.Invoke();
                }
                #endregion

                #region Build view for tags
                if (source.FilterType.Equals(TileViewType.Topics))
                {
                    _lastVideoSource = "";
                    this.CurrentView = TileViewType.Topics;
                    BuildMediaTags();
                }
                #endregion
            }
        }
        protected void PrepThumbnail(object args)
        {
            MediaMetaData source = (MediaMetaData)args;
            source.Thumbnail = new Image(BuildImagePath(source.ThumbnailUrl));
        }
        protected void PostThumbnail(object args)
        {
            MediaMetaData source = (MediaMetaData)args;
            if (source.Parent.Equals(_lastVideoSource))
            {
                MediaListItem mli = new MediaListItem(source);
                this.VideoMetaDataList.Add(mli);
            }
        }

        protected void PrepTimeline(object args)
        {
            Storage st = new Storage();
            ArrayListDataSet tempResults = (ArrayListDataSet)args;

            Dictionary<string, TimelineMetaData> myTimelines = new Dictionary<string, TimelineMetaData>();
            foreach (ClipShowContent cms in st.GetMediaLibraries())
            {
                foreach (MediaMetaData item in cms.MediaItems)
                {
                    string dateKey = String.Format("{0}:{1}", item.CreationDateTime.Year, item.CreationDateTime.Month);
                    string yearKey = item.CreationDateTime.Year.ToString();

                    if (!myTimelines.ContainsKey(dateKey))
                    {
                        TimelineMetaData tmd = new TimelineMetaData();
                        tmd.MediaMonth = item.CreationDateTime.Month;
                        tmd.MediaYear = item.CreationDateTime.Year;
                        tmd.TimelineMediaItems.Add(item);
                        myTimelines.Add(dateKey, tmd);
                    }
                    else
                    {
                        myTimelines[dateKey].TimelineMediaItems.Add(item);
                    }
                    if (!myTimelines.ContainsKey(yearKey))
                    {
                        TimelineMetaData tmd = new TimelineMetaData();
                        tmd.MediaMonth = 0;
                        tmd.MediaYear = item.CreationDateTime.Year;
                        tmd.TimelineMediaItems.Add(item);
                        myTimelines.Add(yearKey, tmd);
                    }
                    else
                    {
                        myTimelines[yearKey].TimelineMediaItems.Add(item);
                    }
                }
            }

            foreach (string dateKey in myTimelines.Keys)
            {
                PreviewChannelItem pci = new PreviewChannelItem();
                string itemName = "";
                if (dateKey.Contains(":"))
                {
                    itemName = String.Format("{0} {1}", MonthConvert(myTimelines[dateKey].MediaMonth),
                        myTimelines[dateKey].MediaYear.ToString());
                }
                else
                {
                    itemName = String.Format("Media from {0}", myTimelines[dateKey].MediaYear.ToString());
                }

                pci.Name = itemName;
                pci.TimelineMonth = myTimelines[dateKey].MediaMonth;
                pci.TimelineYear = myTimelines[dateKey].MediaYear;
                MediaMetaData med = (MediaMetaData)myTimelines[dateKey].TimelineMediaItems[0];
                pci.MediaItems.AddRange(myTimelines[dateKey].TimelineMediaItems);
                pci.ThumbnailUrl = med.ThumbnailUrl;
                pci.Count = myTimelines[dateKey].TimelineMediaItems.Count;

                tempResults.Add(pci);
            }

            // Sort the list by date (Year,Month)
            IComparer myComparer = new PciTimelineComparer();
            tempResults.Sort(myComparer);
        }
        protected void PostTimeline(object args)
        {
            ArrayListDataSet tempResults = (ArrayListDataSet)args;
            _myTimelineVItems.Clear();
            foreach (PreviewChannelItem pci in tempResults)
            {
                Application.DeferredInvokeOnWorkerThread(new DeferredHandler(PrepTimelineThumbnail), new DeferredHandler(PostTimelineThumbnail), pci);
            }
        }
        protected void PrepTimelineThumbnail(object args)
        {
            PreviewChannelItem pci = (PreviewChannelItem)args;
            if (this.AppSettings.UseEffects)
            {
                pci.Thumbnail = new Image(BuildImagePath(pci.ThumbnailUrl));
            }
            else
            {
                pci.Thumbnail = new Image("resx://ClipShow/ClipShow.Resources/clipShow_glyph");
            }
        }
        protected void PostTimelineThumbnail(object args)
        {
            PreviewChannelItem pci = (PreviewChannelItem)args;
            PreviewChannelVItem pcVi = new PreviewChannelVItem(pci);
            _myTimelineVItems.Add(pcVi);
        }

        public void BuildLibraryOptions(bool includeChannels, bool includeSnags)
        {
            _myMediaLibraries = new Choice();

            Storage st = new Storage();
            ArrayList sources = st.GetMediaLibraries();
            ArrayListDataSet _tempSources = new ArrayListDataSet();
            if (sources.Count > 0)
            {
                foreach (ClipShowContent cm in sources)
                {
                    _tempSources.Add(cm);
                }
                if (includeChannels)
                {
                    if (st.GetMyCollections().Count > 0)
                    {
                        ClipShowContent channels = new ClipShowContent();
                        channels.ContentSourceName = "my playlists";
                        _tempSources.Add(channels);
                    }
                }
                if(includeSnags) 
                {
                    if (st.GetSnagCollection().MediaItems.Count > 0)
                    {
                        ClipShowContent snag = st.GetSnagCollection();
                        _tempSources.Add(snag);
                    }
                }
            }
            else
            {
                _tempSources.Add(new ClipShowContent());
            }

            _myMediaLibraries.Options = _tempSources;
        }

        public void AddCommandBarItems(ArrayListDataSet source)
        {
            _commandBarItems = new Choice();
            _commandBarItems.Options = source;
        }
        public void AddMediaFilterItems(ArrayListDataSet source)
        {
            _myMediaFilters.Options = source;
        }
        public void StopPlayback(bool saveSettings)
        {
            try
            {
                AddInHost.Current.MediaCenterEnvironment.MediaExperience.Transport.PlayRate = 0;
            }
            catch
            {
                // Ignore error
            }
            finally
            {
                if (saveSettings)
                {
                    SaveSettings();
                }
            }
        }

        public void SaveSettings()
        {
            try
            {
                // Save current state settings
                Storage st = new Storage();
                st.PersistSettings(_settings);
            }
            catch(SystemException se)
            {
                System.Diagnostics.EventLog.WriteEntry("clipShow.SaveSettings", se.Message);
                ShowDialog("Exception saving settings", se.Message, true);
            }
        }

        public void InVideoArea()
        {
            _currentFocusArea = FocusAreas.VideoTile;
            _updateStatusBar.Invoke();
        }
        public void InChosenTimelineTileArea2(int tileIndex, PreviewChannelItemList sourceTiles)
        {
            _currentTileIndex = tileIndex;
            _currentFocusArea = FocusAreas.TimelineTiles;
            _browseTiles2 = sourceTiles;
            _updateStatusBar.Invoke();
        }
        public void InChosenTimelineTileArea(int tileIndex, Choice sourceTiles)
        {
            _currentTileIndex= tileIndex;
            _currentFocusArea = FocusAreas.TimelineTiles;
            _browseTiles = sourceTiles;
            _updateStatusBar.Invoke();
        }
        public void InChosenPlaylistTileArea(int tileIndex, Choice sourceTiles)
        {
            _currentFocusedVideoIndex = tileIndex;
            _currentFocusArea = FocusAreas.PlaylistSelectionTiles;
            _browseTiles = sourceTiles;
            _updateStatusBar.Invoke();
        }
        MediaList _browseTiles3;
        public void InChosenTileArea(int tileIndex, MediaList sourceTiles)
        {
            _currentFocusedVideoIndex = tileIndex;
            _currentFocusArea = FocusAreas.MediaPlayTiles;
            _browseTiles3 = sourceTiles;
            _updateStatusBar.Invoke();
        }
        public void InSingleMediaTileArea(int tileIndex)
        {
            _currentTileIndex = tileIndex;
            _currentFocusArea = FocusAreas.LinkedTiles;
            _updateStatusBar.Invoke();
        }
        public void InTagTileArea(int tileIndex, Choice sourceTiles)
        {
            _currentTileIndex = tileIndex;
            _currentFocusArea = FocusAreas.TagTiles;
            _browseTiles = sourceTiles;
            _updateStatusBar.Invoke();
        }
        PreviewChannelItemList _browseTiles2;
        public void InTagTileArea2(int tileIndex, PreviewChannelItemList sourceTiles)
        {
            _currentTileIndex = tileIndex;
            _currentFocusArea = FocusAreas.TagTiles;
            _browseTiles2 = sourceTiles;
            _updateStatusBar.Invoke();
        }
        public void InSnagTileArea(int tileIndex, PreviewChannelItemList sourceTiles)
        {
            _currentTileIndex = tileIndex;
            _currentFocusArea = FocusAreas.SnagTiles;
            _browseTiles2 = sourceTiles;
            _updateStatusBar.Invoke();
        }
        public void InPlaylistTileArea(int tileIndex, PreviewChannelItemList sourceTiles)
        {
            _currentTileIndex = tileIndex;
            _currentFocusArea = FocusAreas.SelectionTiles;
            _browseTiles2 = sourceTiles;
            _updateStatusBar.Invoke();
        }
        public void InToplineArea(int topicIndex, Choice sourceTiles)
        {
            _currentTopicIndex = topicIndex;
            _currentFocusArea = FocusAreas.ToplineSelection;
            _browseTiles = sourceTiles;
            _updateStatusBar.Invoke();
        }

        public void InMenuBar(int menuIndex)
        {
            _currentMenuIndex = menuIndex;
            _currentFocusArea = FocusAreas.MenuBar;
            _updateStatusBar.Invoke();
        }
        public void InMenuButton(string description)
        {
            _currentFocusArea = FocusAreas.ButtonBar;
            _buttonBarDescription = description;
            _updateStatusBar.Invoke();
        }
        public void ProcessCommand(int commandIndex)
        {
            _lastCommandIndex = commandIndex;
            _commandBarClick.Invoke();
        }
        #endregion

        #region Core private methods
        internal static void RandomizeMediaList(MediaList arrayList, Random random)
        {
            if (arrayList == null) { return; }
            int count = arrayList.Count;
            for (int i = 0; i < count; i++)
            {
                MediaListItem tmp = (MediaListItem)arrayList[i];
                int nextIndex = random.Next(count);

                arrayList[i] = arrayList[nextIndex];
                arrayList[nextIndex] = tmp;
            }
        }
        internal static void RandomizeArrayListDataSet(ArrayListDataSet arrayList, Random random)
        {
            if (arrayList == null) { return; }
            int count = arrayList.Count;
            for (int i = 0; i < count; i++)
            {
                Object tmp = arrayList[i];
                arrayList.RemoveAt(i);
                arrayList.Insert(random.Next(count), tmp);
            }
        }

        internal static string BuildImagePath(string sourceUrl)
        {
            if (sourceUrl.StartsWith("http"))
            {
                return (sourceUrl);
            }
            else
            {
                if (File.Exists(sourceUrl))
                {
                    return (String.Format("file://{0}", sourceUrl));
                }
                else
                {
                    return ("resx://ClipShow/ClipShow.Resources/clipShow_glyph");
                }
            }
        }
        static string StripRTF(string source)
        {
            if (source.StartsWith("{\\rtf"))
            {
                string result = source.Remove(0, 5);
                return (result.Substring(0,result.Length-1).Trim());
            }
            else
            {
                return (source);
            }
        }

        /// <summary>
        /// Creates an ArrayListDataSet with specified keywords
        /// </summary>
        /// <param name="searchText"></param>
        /// <returns></returns>
        //private static ArrayListDataSet PopulateMediaLibrary(string searchText)
        //{
        //    Storage st = new Storage();
        //    ArrayListDataSet tempResults = new ArrayListDataSet();
        //    foreach (ClipShowContent cms in st.GetMediaLibraries())
        //    {
        //        foreach (MediaMetaData med in cms.MediaItems)
        //        {
        //            if (med.Description.ToLower().Contains(searchText.ToLower()))
        //            {
        //                med.Thumbnail = new Image(BuildImagePath(med.ThumbnailUrl));
        //                tempResults.Add(med);
        //            }
        //            else if (med.Title.ToLower().Contains(searchText.ToLower()))
        //            {
        //                med.Thumbnail = new Image(BuildImagePath(med.ThumbnailUrl));
        //                tempResults.Add(med);
        //            }
        //            else if (med.Author.ToLower().Contains(searchText.ToLower()))
        //            {
        //                med.Thumbnail = new Image(BuildImagePath(med.ThumbnailUrl));
        //                tempResults.Add(med);
        //            }
        //        }
        //    }
        //    return (tempResults);
        //}

        /// <summary>
        /// Creates an ArrayListDataSet with all known media items
        /// </summary>
        /// <returns></returns>
        internal ArrayListDataSet PopulateMediaLibrary()
        {
            ArrayListDataSet tempResults = new ArrayListDataSet();
            foreach (ClipShowContent cm in this.MediaLibraries.Options)
            {
                ArrayList temp = cm.MediaItems;
                foreach (MediaMetaData item in temp)
                {
                    try
                    {
                        if (!item.Title.Equals("N/A"))
                        {
                            item.Thumbnail = new Image(BuildImagePath(item.ThumbnailUrl));
                            tempResults.Add(item);
                        }
                    }
                    catch
                    {

                    }
                }
            }
            return (tempResults);
        }

        /// <summary>
        /// Creates an ArrayListDataSet with known media items from library index
        /// </summary>
        /// <param name="libraryIndex">Library index in Media Library collection</param>
        /// <returns></returns>
        private ArrayListDataSet PopulateMediaLibrary(int libraryIndex)
        {
            // Check cache first
            if (_cachedMediaItems.ContainsKey(libraryIndex))
            {
                return (_cachedMediaItems[libraryIndex]);
            }
            else
            {
                ClipShowContent cm = (ClipShowContent)this.MediaLibraries.Options[libraryIndex];
                ArrayList temp = cm.MediaItems;
                ArrayListDataSet tempResults = new ArrayListDataSet();

                foreach (MediaMetaData item in temp)
                {
                    if (!item.Title.Equals("N/A"))
                    {
                        tempResults.Add(item);
                    }
                }
                _cachedMediaItems.Add(libraryIndex, tempResults);
                return (tempResults);
            }
        }

        internal static string MonthConvert(int Month)
        {
            switch (Month)
            {
                case 1: return ("January");
                case 2: return ("February");
                case 3: return ("March");
                case 4: return ("April");
                case 5: return ("May");
                case 6: return ("June");
                case 7: return ("July");
                case 8: return ("August");
                case 9: return ("September");
                case 10: return ("October");
                case 11: return ("November");
                case 12: return ("December");
                default: return ("");
            }
        }
        #endregion
    }
}
